﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace tactics.MapBuilders
{
    class PlainsBuilder : IMapBuilder
    {
        int width;
        int height;
        float scale;

        TileInfo[] mapInfo;

        #region Properties

        public int Width
        {
            get { return width; }
        }

        public int Height
        {
            get { return height; }
        }

        public float Scale
        {
            get { return scale; }
        }

        public string TileXMLFile
        {
            get { return "Content/TileSets/plains.xml"; }
        }

        public TileInfo[] MapInfo
        {
            get { return mapInfo; }
        }

        public bool SmoothTerrain
        {
            get { return false; }
        }

        #endregion

        public PlainsBuilder(int widthIn, int heightIn, float scaleIn)
        {
            width = widthIn;
            height = heightIn;
            scale = scaleIn;
        }

        public HeightMap GenerateMap(TileSet tileSet)
        {
            HeightMap heightMap = new HeightMap(width, height, scale, 10f, 30f, 2f, 0);
            heightMap.GeneratePerlinHeightMap();

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    heightMap.SetHeight(x, y, (float)Math.Round(heightMap.GetHeight(x, y)) / 2);
                    //heightMap.SetHeight(x, y, heightMap.GetHeight(x, y));
                }
            }

            GenerateTiles(tileSet, heightMap);
            return heightMap;
        }

        private void GenerateTiles(TileSet tileSet, HeightMap heightMap)
        {
            Random r = new Random(heightMap.Seed);

            mapInfo = new TileInfo[width * height];

            int idx = 0;
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    string type = "Rock";
                    float currHeight = heightMap.GetHeight(x, y);

                    bool flat = true;
                    float averageHeight = currHeight;

                    if (x != width - 1 && y != height - 1)
                    {
                        averageHeight = currHeight +
                                        heightMap.GetHeight(x + 1, y) +
                                        heightMap.GetHeight(x, y + 1) +
                                        heightMap.GetHeight(x + 1, y + 1);

                        flat = currHeight == heightMap.GetHeight(x + 1, y) &&
                                currHeight == heightMap.GetHeight(x, y + 1) &&
                                currHeight == heightMap.GetHeight(x + 1, y + 1);
                    }

                    averageHeight /= 4;

                    if (averageHeight >= 1.25 || (averageHeight >= 0 && !flat))
                        type = "Rock";
                    else if (averageHeight >= 0)
                        type = "Plains";
                    else if (averageHeight >= -0.5f)
                        type = "Sand";
                    else
                        type = "Water";

                    mapInfo[idx] = tileSet.GetTileInfo(type);
                    ++idx;
                }
            }
            
            // flatten water process
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    if (mapInfo[y * width + x] == tileSet.GetTileInfo("Water"))
                    {
                        heightMap.SetHeight(x, y, -1.0f);

                        // attempt to flatten whole square
                        if (x != width - 1)
                            heightMap.SetHeight(x + 1, y, -1.0f);
                        if (y != height - 1)
                            heightMap.SetHeight(x, y + 1, -1.0f);
                        if (x != width - 1 && y != height - 1)
                            heightMap.SetHeight(x + 1, y + 1, -1.0f);
                    }
                }
            }            
        }
    }
}